<?php

namespace App\Services;

use App\Exceptions\BusinessException;
use App\Models\Notice;
use App\Models\Order;
use App\Models\Refund;
use Illuminate\Support\Facades\DB;
use Exception;

class RefundService extends BaseService
{
    /**
     * 退款
     * @param $uid
     * @param $orderId
     * @param $sellType
     * @param $sellId
     * @param $refundReason
     * @return void
     * @throws BusinessException
     */
    public function refund($uid, $orderId, $sellType, $sellId, $refundReason)
    {
        // 获取订单
        $order = Order::query()->where(['id' => $orderId, 'user_id' => $uid])->first();
        if (!$order) {
            $this->throwBusinessException('订单不存在');
        } elseif (!in_array($order->state, [Order::STATE_WAIT_USE, Order::STATE_USE_EXPIRE])) {
            $this->throwBusinessException('订单非待使用/使用过期状态');
        }

        // 获取已退款
        $refund = Refund::query()->where(['order_id' => $orderId, 'state' => Refund::STATE_REFUND_SUCCESS])->first();
        if ($refund) {
            $this->throwBusinessException(Order::sellTypeMap()[$sellType] . '已退款');
        }

        DB::beginTransaction();
        try {
            // 订单
            $order->state = Order::STATE_REFUNDING;
            $order->save();

            // 退款
            $refundData = [
                'user_id' => $order->user_id,
                'camp_id' => $order->camp_id,
                'order_id' => $orderId,
                'sell_type' => $sellType,
                'sell_id' => $sellId,
                'refund_sn' => Refund::getSn(),
                'refund_price' => $order->pay_price,
                'refund_reason' => $refundReason,
                'sell_json' => $order->sell_json,
                'state' => Refund::STATE_WAIT_CHECK,
                'created_at' => date('Y-m-d H:i:s'),
            ];
            Db::table('refund')->insertGetId($refundData);
            DB::commit();
        } catch (Exception $e) {
            DB::rollBack();
            $this->throwBusinessException($e->getMessage());
        }
    }

    /**
     * 退款审核
     * @param $refundId
     * @param $checkStatus
     * @param $rejectReason
     * @return void
     * @throws Exception
     */
    public function refundCheck($refundId, $checkStatus, $rejectReason = '')
    {
        // 获取数据
        $refund = Refund::query()->where(['id' => $refundId])->first();
        if (!$refund) {
            throw new Exception('退款单不存在');
        } elseif ($refund->state != Refund::STATE_WAIT_CHECK) {
            throw new Exception('订单非待审核状态');
        }

        // 获取订单
        $order = Order::query()->where(['id' => $refund->order_id])->first();
        if (!$order) {
            throw new Exception('订单不存在');
        }

        if ($checkStatus == Refund::STATE_PASSED) {
            // 通过
            $result = WechatService::getInstance()->refund(
                [
                    "transaction_id" => $order->transaction_id,
                    "out_trade_no" => $order->order_sn,
                    "out_refund_no" => $refund->refund_sn,
                    "notify_url" => config('app.url') . '/api/refund/notify',
                    "amount" => [
                        "refund" => env('PAY_TEST') ? 1 : (int)number_format($refund->refund_price * 100, 0, '.', ''),
                        "total" => env('PAY_TEST') ? 1 : (int)number_format($refund->refund_price * 100, 0, '.', ''),
                        "currency" => "CNY"
                    ],
                ]
            );

            $refund->state = Refund::STATE_PASSED;
        } else {
            // 拒绝
            $refund->reject_reason = $rejectReason;
            $refund->state = Refund::STATE_REJECTED;
            $order->state = Order::STATE_WAIT_USE;
            $order->save();
        }

        $refund->save();
    }

    /**
     * 退款回调
     * @param $params
     * @return true|void
     */
    public function notify($params)
    {
        // 获取数据
        $data = Refund::query()->where(['refund_sn' => $params['out_refund_no']])->first();
        if ($data && $data->state == Refund::STATE_PASSED) {
            $data->state = Refund::STATE_REFUND_SUCCESS;
            $data->refund_time = date('Y-m-d H:i:s');
            $data->save();
            // 订单
            $order = Order::query()->where(['id' => $data->order_id])->first();
            $order->state = Order::STATE_REFUNDED;
            $order->save();
            // 添加消息
            NoticeService::getInstance()->add(Notice::TYPE_SERVICE, $order->id, $order->user_id, '我的退款', '已退款到账￥' . $data->refund_price);
            return true;
        }
    }
}
